#ifndef _MODBUS_H_
#define _MODBUS_H_

#include "stdint.h"

#define DEFAULT_ID 0x02
#define TIMEOUT_DEFAULT 3
#define UART_DMA 1

// 功能码
#define MB_FUNCODE_RSWIN 0x02
#define MB_FUNCODE_RSWOUT 0x01
#define MB_FUNCODE_RREG 0x03
#define MB_FUNCODE_WSWOUT 0x05
#define MB_FUNCODE_WREG 0x06
#define MB_FUNCODE_WSWOUTS 0x0F
#define MB_FUNCODE_WREGS 0x10

typedef enum
{
    MB_OK = 0,
    MB_FUNCODE_ERR = 0x01,
    MB_DATA_ADDR_ERR,  // 地址错误
    MB_DATA_VALUE_ERR, // 数据值错误
    MB_UNIT_ERROR,
    MB_CODE_ERROR,
    MB_BUSY_ERROR, //
} MB_ERR_Typedef;

typedef struct
{
    uint8_t MB_Addr;        // 地址
    uint8_t MB_FunCode;     // 功能码
    uint16_t MB_RegStaAddr; // 寄存器地址
    uint16_t CRC16;
    uint16_t *DataAddr;
    // 写多路寄存器
    uint16_t MB_WORDLEN; // 写多个字长
    uint8_t MB_BYTELEN;  // 写多个字节长
    // ERROR
    MB_ERR_Typedef MB_ERROR;
} MODBUS_Typedef;

typedef struct
{
    unsigned int RB_Index;
    unsigned int RB_Outdex;
    unsigned int buf_size;
    unsigned int BufEmpty;
    unsigned char *RB_Data;
    unsigned long long timestamp;
} MB_RF_Buf_t;

typedef struct
{
    uint8_t Local_add; // 地址
    MB_RF_Buf_t MB_Buf;
    uint16_t MB_Buad;    // 波特率(算超时时间)
    uint16_t MB_Timeout; // 超时时间
    uint64_t (*GetTimestampus)(void);
    void (*ModbusSendBytes)(uint8_t *data, uint16_t datalen);
    MB_ERR_Typedef (*MB_ReadSwitchInHandler)(uint16_t StartAddr, uint8_t *data, uint16_t Datalen);
    MB_ERR_Typedef (*MB_ReadSwitchOutHandler)(uint16_t StartAddr, uint8_t *data, uint16_t Datalen);
    MB_ERR_Typedef (*MB_WriteSwitchOutHandler)(uint16_t StartAddr, uint16_t *data);
    MB_ERR_Typedef (*MB_ReadRegHandler)(uint16_t StartAddr, uint16_t *data, uint16_t Datalen); // 设置用户读取函数
    MB_ERR_Typedef (*MB_WriteSwitchOuts)(uint16_t StartAddr, uint8_t *data, uint16_t OutNum);
    MB_ERR_Typedef (*MB_WriteRegHandler)(uint16_t StartAddr, uint16_t *data, uint16_t Datalen); // 设置用户写入函数
} Modbus_t;

extern uint8_t DEV_ID;

#define REG16SWAP(data) (((data << 8) & 0xFF00) | ((data >> 8) & 0x00FF))
#define REG32SWAP(data) (((data << 24) & 0xFF000000) | ((data << 8) & 0x00FF0000) | ((data >> 8) & 0x0000FF00) | ((data >> 24) & 0x000000FF))

void MB_AddRxDataBuf(Modbus_t *modbus, uint32_t dataAddr, uint16_t buffsize);
void MB_AddGetTimestamp(Modbus_t *modbus, uint64_t (*GetTimestampus)(void));
void MB_AddSendBytes(Modbus_t *modbus, void (*ModbusWriteBytes)(uint8_t *data, uint16_t datalen));
void MB_SetLocalAddr(Modbus_t *modbus, uint8_t Addr);
void MB_SetBuad(Modbus_t *modbus, uint32_t buad);

void MB_SetReadRegs_UserFun(Modbus_t *modbus, MB_ERR_Typedef (*MB_ReadRegHandler)(uint16_t StartAddr, uint16_t *data, uint16_t Datalen));
void MB_SetWriteRegs_UserFun(Modbus_t *modbus, MB_ERR_Typedef (*MB_WriteRegHandler)(uint16_t StartAddr, uint16_t *data, uint16_t Datalen));
void MB_SetReadSWIN_UserFun(Modbus_t *modbus, MB_ERR_Typedef (*MB_ReadSwitchInHandler)(uint16_t StartAddr, uint8_t *data, uint16_t Datalen));
void MB_SetReadSWOUT_UserFun(Modbus_t *modbus, MB_ERR_Typedef (*MB_ReadSwitchOutHandler)(uint16_t StartAddr, uint8_t *data, uint16_t Datalen));
void MB_SetWriteSWOUT_UserFun(Modbus_t *modbus, MB_ERR_Typedef (*MB_WriteSwitchOutHandler)(uint16_t StartAddr, uint16_t *data));
void MB_SetWriteSWOUTS_UserFun(Modbus_t *modbus, MB_ERR_Typedef (*MB_WriteSwitchOuts)(uint16_t StartAddr, uint8_t *data, uint16_t OutNum));

void Modbus_Parse(Modbus_t *modbus);
void MB_WriteByte(Modbus_t *modbus, unsigned char data);
unsigned int MB_ReadBytes(Modbus_t *modbus, unsigned char *data, unsigned int Datalen);

#endif
